﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Text;
using System.Net;
using System.IO;
using System.Threading;

namespace KFGame
{
    /// <summary>
    /// 状态器
    /// </summary>
    internal class WebReqState
    {

        public byte[] Buffer;
        public const int BufferSize = 1024;

        //缓存流
        public Stream fs;

        //网络流
        public Stream OrginalStream;

        //请求返回
        public HttpWebResponse WebResponse;

        public string filename;

        public WebReqState(string path, bool isfile)
        {
            filename = path;

            Buffer = new byte[1024];

            if (isfile)
                fs = new FileStream(path, FileMode.Create);
            else
                fs = new MemoryStream();
        }

    }


    /// <summary>
    /// 请求结构体
    /// </summary>
    public class WebRequestData
    {
        //请求的线程
        public Thread requestThread;
        //标记这次请求的名字
        public string name = "requestname";
        //下载文件
        public bool isloadFile = false;
        //请示地址
        public string httpurl;
        //下载缓存路径
        public string path = null;
        //下载的文件名
        public string fileName;

        public string method = "POST";
        public string contentType = "application/json";
        public int ReadWriteTimeout = 5000;
        public bool KeepAlive = true;
        public string requestDatas = "";
        public Dictionary<String, String> handes = new Dictionary<String, String>();

        //得到数据
        public string datas;


        //保存代理
        public delegate void CALLBACK(string name, string url, WebRequestData datas);
        public CALLBACK onCallBack;

    }

    public class HttpHelper
    {

        public WebRequestData data;
        public delegate void Success(string name, WebRequestData datas);
        public Success onSuccess;
        public delegate void Error(string name, string message);
        public Error onError;

        public HttpHelper(WebRequestData d)
        {
            if (d == null)
                this.data = new WebRequestData();
            else
                this.data = d;
        }

        //添加头
        public void addHeader(string key, string value)
        {
            data.handes.Add(key, value);
        }

        /// <summary>
        /// 异步 GET 
        /// </summary>
        /// <param name="url"></param>
        public void AsyncGET(string url = null)
        {
            if (url != null)
                data.httpurl = url;

            data.method = "GET";
            toRequest();
        }

        /// <summary>
        /// 异步 post
        /// </summary>
        /// <param name="url"></param>
        /// <param name="parameters"></param>
        public void AsyncPOST(string url = null, string parameters = null)
        {
            if (parameters != null)
                data.requestDatas = parameters;

            if (url != null)
                data.httpurl = url;

            data.method = "POST";

            toRequest();
        }


        /// <summary>
        /// 异步一下载
        /// </summary>
        /// <param name="url"></param>
        public void AsyDownLoad(string url)
        {
            data.isloadFile = true;
            AsyncGET(url);
        }



        /// <summary>
        /// 请求网络 使用 WebRequestData 对象配置 主要数据 requestDatas
        /// 
        /// </summary>
        public void toRequest()
        {

            HttpWebRequest httpRequest = WebRequest.Create(data.httpurl) as HttpWebRequest;
            httpRequest.Method = data.method;
            httpRequest.ContentType = data.contentType;
            httpRequest.ReadWriteTimeout = data.ReadWriteTimeout;
            httpRequest.KeepAlive = data.KeepAlive;

            foreach (KeyValuePair<string, string> kv in data.handes)
                httpRequest.Headers.Add(kv.Key, kv.Value);

            if (data.method == "POST")
            {
                byte[] bytes = Encoding.UTF8.GetBytes(data.requestDatas);
                httpRequest.ContentLength = bytes.Length;
                Stream strStream = httpRequest.GetRequestStream();
                strStream.Write(bytes, 0, bytes.Length);
                strStream.Close();
            }


            httpRequest.BeginGetResponse(new AsyncCallback(ResponseCallback), httpRequest);

        }

        /// <summary>
        /// 请求返回，异步回调
        /// </summary>
        /// <param name="ar"></param>
        void ResponseCallback(IAsyncResult ar)
        {

            try
            {
                HttpWebRequest req = ar.AsyncState as HttpWebRequest;
                if (req == null) return;

                HttpWebResponse response = req.EndGetResponse(ar) as HttpWebResponse;


                if (response.StatusCode != HttpStatusCode.OK)
                {
                    response.Close();
                    if (onError != null)
                        onError(data.name, response.StatusDescription);
                    return;
                }

                WebReqState st = new WebReqState(data.path + "/" + data.fileName, data.isloadFile);
                st.WebResponse = response;
                Stream responseStream = response.GetResponseStream();
                st.OrginalStream = responseStream;
                responseStream.BeginRead(st.Buffer, 0, WebReqState.BufferSize, new AsyncCallback(ReadDataCallback), st);
            }
            catch (System.Exception ex)
            {
                Debug.LogError("error :" + ex.ToString());
                if (onError != null)
                    onError(data.name, ex.ToString());
            }

        }

        /// <summary>
        /// 网络请求返回，解析数据 抛出代理， WebRequestData 对象，返回数据存在 datas
        /// </summary>
        /// <param name="ar"></param>
        void ReadDataCallback(IAsyncResult ar)
        {
            try
            {
                WebReqState rs = ar.AsyncState as WebReqState;
                int read = rs.OrginalStream.EndRead(ar);
                if (read > 0)
                {
                    rs.fs.Write(rs.Buffer, 0, read);
                    rs.fs.Flush();
                    rs.OrginalStream.BeginRead(rs.Buffer, 0, WebReqState.BufferSize, new AsyncCallback(ReadDataCallback), rs);
                    return;
                }


                if (onSuccess != null)
                {
                    if (data.isloadFile)
                        data.datas = rs.filename;
                    else
                    {
                        rs.fs.Position = 0;
                        StreamReader streamReader = new StreamReader(rs.fs, System.Text.Encoding.UTF8);
                        data.datas = streamReader.ReadToEnd();

                    }

                    onSuccess(data.name, data);
                }

                rs.fs.Close();
                rs.OrginalStream.Close();
                rs.WebResponse.Close();

            }
            catch (System.Exception ex)
            {
                Debug.LogError("error :" + ex.ToString());
                if (onError != null)
                    onError(data.name, ex.ToString());
            }
        }
    }
}